#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//wav的头部第一部分
typedef struct WAV_HEADER 
{
    char chunkid[4];
    unsigned long chunksize;
    char format[4];
}pcmHeader; //12字节

//wav的头部第二部分，保存着文件的采样率、通道数、码率等等一些基础参数
typedef struct WAV_FMT 
{
    char subformat[4];
    unsigned long sbusize;
    unsigned short audioFormat;
    unsigned short numchannels;
    unsigned long sampleRate;
    unsigned long byteRate;
    unsigned short blockAlign;
    unsigned short bitPerSample;
}pcmFmt; //24字节

typedef struct WAV_DATA 
{
    char wavdata[4];
    unsigned long dataSize;
}pcmData; //8字节

//获取文件大小
long getFileSize(const char* filename)
{
    FILE* fp = fopen(filename, "r");
    if (!fp) 
    {
        return -1;
    }
    fseek(fp, 0, SEEK_END);
    long size = ftell(fp);
    fclose(fp);
    return size;
}

//PCM格式转为WAV格式
int pcm2wav(const char* pcmpath,
            int channles, int sample_rate, int fmtsize,
            const char* wavpath, int bits)
{
    FILE* fp, * fpout;
    WAV_HEADER pcmHeader;
    WAV_FMT pcmFmt;
    WAV_DATA pcmData;

    //打开输入的文件流
    fp = fopen(pcmpath, "rb");
    if (fp == NULL)
    {
        printf("fopen failed\n");
        return -1;
    }
    //获取pcm文件大小
    int pcm_size = getFileSize((char*)pcmpath);
    if (pcm_size==-1) //文件打开失败
    {
        printf("get pcm file size fail");
        return -1;
    }

    //第一部分
    memcpy(pcmHeader.chunkid, "RIFF", 4);//字符REFF
    long fileSize = 44 + pcm_size - 8;//三部分共44个字节，排除ChunkID和ChunkSize这8个字节
    pcmHeader.chunksize = fileSize;//wav文件大小
    memcpy(pcmHeader.format, "WAVE", 4);//字符WAVE

    //第二部分
    memcpy(pcmFmt.subformat, "fmt ", 4);//字符串fmt
    pcmFmt.sbusize = fmtsize;//存储位宽
    pcmFmt.audioFormat = 1;//pcm数据标识
    pcmFmt.numchannels = channles; //通道数
    pcmFmt.sampleRate = sample_rate;//采样率
    pcmFmt.byteRate = sample_rate * channles * bits / 8;//每秒传递的比特数
    pcmFmt.blockAlign = channles * bits / 8;
    pcmFmt.bitPerSample = bits;//样本格式，16位。

    //第三部分
    memcpy(pcmData.wavdata, "data", 4);//字符串data
    pcmData.dataSize = pcm_size;//pcm数据长度

    //打开输出的文件流
    fpout = fopen(wavpath, "wb");
    if (fpout == NULL)
    {
        printf("fopen failed\n");
        return -1;
    }
    //写入wav头部信息44个字节
    fwrite(&pcmHeader, sizeof(pcmHeader), 1, fpout);
    fwrite(&pcmFmt, sizeof(pcmFmt), 1, fpout);
    fwrite(&pcmData, sizeof(pcmData), 1, fpout);
    //创建缓存空间
    char* buff = (char*)malloc(512);
    int len;
    //读取pcm数据写入wav文件
    while ((len = fread(buff, sizeof(char), 512, fp)) != 0) 
    {
        fwrite(buff, sizeof(char), len, fpout);
    }
    free(buff);
    fclose(fp);
    fclose(fpout);
    return 0;
}

int main(int argc, const char* argv[])
{
    pcm2wav("../resource/10s_48000_2_f32le.pcm", 2, 48000, 32, "audio.wav", 32);
    return 0;
}



